package com.bupt.ilink.controller;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bupt.ilink.entity.*;
import com.bupt.ilink.mapper.ApplicationTemplateMapper;
import com.bupt.ilink.service.*;
import com.bupt.ilink.utils.R;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@RestController
public class ModelMetadataController {
    @Autowired
    private ModelMetadataService modelMetadataService;

    @Autowired
    private ModelTagsService modelTagsService;

    @Autowired
    private ModelLangflowService modelLangflowService;

    @Autowired
    private ApplicationTemplateMapper applicationTemplateMapper;


    @Autowired
    private OssService ossService;

    //  雪花算法
    private final Snowflake snowflake = IdUtil.getSnowflake(1, 1);


    private static final Logger logger = LoggerFactory.getLogger(ModelMetadataController.class);

    /**
     * @author dzy
     * @return 最常使用的8个标签(List<String>形式)
     */
    @GetMapping("/getCommonModelTags")
    public R getCommonDatasetTags(){
        try {
            return R.ok(modelTagsService.getCommonTags());
        } catch(Exception e){
            return R.failure("内部服务器错误：" + e);
        }
    }

    //  csv批量插入model元数据
    @PostMapping("/csvBatchInsertModel")
    public R csvBatchInsertModel(@RequestBody MultipartFile file){

        // 查询数据库中的所有名称，确保不重复
        Set<String> existingNames = new HashSet<>(modelMetadataService.getAllNames()); 
        
        List<ModelMetadata> metadataList = new ArrayList<>();
        List<ModelTags> tagsList = new ArrayList<>();

        //  读取csv文件
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8));
             CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withFirstRecordAsHeader())) {

            // 打印列名称
            System.out.println("CSV文件头部: " + csvParser.getHeaderMap().keySet());

            int count = 0;

            for (CSVRecord record : csvParser) {
                // 确保name列不为空
                String name = record.get("model_name");
                if (name == null || name.trim().isEmpty() || existingNames.contains(name)) {
                    System.out.println("跳过行，name为空或重复: " + record.toString());
                    continue; // 跳过name为空或重复的行
                }

                existingNames.add(name); // 添加到已存在的名称集合中

                ModelMetadata metadata = new ModelMetadata();
                //  雪花算法分配model_id
                metadata.setModelId(snowflake.nextId());
                //  无重复model_name
                metadata.setModelName(name);
                System.out.println(name);
                //  设置model_label
                metadata.setModelLabel(record.isSet("model_label") ? record.get("model_label") : "");
                //  设置description
                metadata.setDescription(record.isSet("description") ? record.get("description") : "");
                //  设置version_id
                metadata.setVersionId(record.isSet("version_id") ? record.get("version_id") : "");
                // 处理 version_num 字段，确保不为空且是有效的整数
                String versionNumStr = record.get("version_num");
                int versionNum = 1; // 默认值为1
                if (versionNumStr != null && !versionNumStr.trim().isEmpty()) {
                    try {
                        versionNum = Integer.parseInt(versionNumStr);
                    } catch (NumberFormatException e) {
                        // 处理转换错误，可以记录日志或采取其他措施
                        System.err.println("Invalid version_num: " + versionNumStr);
                    }
                }
                metadata.setVersionNum(versionNum);

                //  设置为disclaimer
                metadata.setDisclaimer(record.isSet("disclaimer") ? record.get("disclaimer") : "");

                metadataList.add(metadata);

                String tagsString = record.isSet("tags") ? record.get("tags") : "";
                String[] tags = tagsString.split("、");
                for (String tag : tags) {
                    ModelTags modelTag = new ModelTags();
                    modelTag.setTagId(snowflake.nextId());
                    modelTag.setModelId(metadata.getModelId());
                    modelTag.setTag(tag.trim());
                    tagsList.add(modelTag);
                }

                modelMetadataService.saveBatch(metadataList);
                modelTagsService.saveBatch(tagsList);
                metadataList.clear();
                tagsList.clear();
                System.out.println("已处理 " + count + " 条记录");
            }

        } catch (IOException e) {
            e.printStackTrace();
            return R.failure("文件处理失败");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return R.failure("CSV文件头部列名称不匹配: " + e.getMessage());
        }

        return R.ok("公开数据集批量插入成功");
    }

    //  【模型广场】-【首页】-返回【ID，名，定义，描述，标签列表，icon图片】
    //  根据关键词查询：keywords
    //  根据厂商查询：tag
    @GetMapping("/getModelMetadata")
    public IPage<ModelHomepageResponse> getModelMetadata(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(required = false) String tag,
            @RequestParam(required = false) String keywords){
        int size = 12;
        // 创建分页对象
        Page<ModelMetadata> pageRequest = new Page<>(page, size);

        // 根据关键词和标签进行分页查询模型元数据
        IPage<ModelMetadata> metadataPage;
        if ((keywords == null || keywords.isEmpty()) && (tag == null || tag.isEmpty())) {
            metadataPage = modelMetadataService.getAllModelsByPage(pageRequest);
        } else if (keywords != null && !keywords.isEmpty() && (tag == null || tag.isEmpty())) {
            metadataPage = modelMetadataService.getModelsByKeywords(pageRequest, keywords);
        } else if ((keywords == null || keywords.isEmpty()) && tag != null && !tag.isEmpty()) {
            metadataPage = modelMetadataService.getModelsByTag(pageRequest, tag);
        } else {
            metadataPage = modelMetadataService.getModelsByKeywordsAndTag(pageRequest, keywords, tag);
        }

        // 将结果转换为 ModelResponse 格式
        IPage<ModelHomepageResponse> responsePage = metadataPage.convert(
                metadata -> {
            String name = metadata.getModelName();
            List<ModelTags> tagsList = modelTagsService.getTagsByModelId(metadata.getModelId());
            List<String> tags = tagsList.stream().map(ModelTags::getTag).collect(Collectors.toList());

            String url = ossService.getIconUrl
                    ("dataset-square","model_icon/" + name);
            logger.info("生成icon URL for model {}: {}", name, url);

            ModelHomepageResponse response = new ModelHomepageResponse();
            response.setModelId(metadata.getModelId());
            response.setModelName(metadata.getModelName());
            response.setModelLabel(metadata.getModelLabel());
            response.setDescription(metadata.getDescription());
            response.setTags(tags);
            response.setIconUrl(url);
            return response;
        });

        return responsePage;
    }

    //  【模型广场】-【详情页】-返回【ID，名，标签列表，模型ID，版本数量，模型介绍，免责声明】
    @GetMapping("/getModelInformation")
    public ModelInformationResponse getModelMetadata(@RequestParam String targetId){

        ModelMetadata metadata = modelMetadataService.selectById(targetId);
        List<ModelTags> tagsList = modelTagsService.getTagsByModelId(Long.valueOf(targetId));
        List<String> tags = tagsList.stream().map(ModelTags::getTag).collect(Collectors.toList());

        String name = metadata.getModelName();
        String url = ossService.getIconUrl
                ("dataset-square","model_icon/" + name);
        logger.info("生成icon URL for model {}: {}", name, url);

        ModelInformationResponse response = new ModelInformationResponse();
        response.setModelId(metadata.getModelId());
        response.setModelName(metadata.getModelName());
        response.setTags(tags);
        response.setIconUrl(url);
        response.setVersionId(metadata.getVersionId());
        response.setVersionNum(metadata.getVersionNum());

        response.setDescription(metadata.getDescription());
        response.setDisclaimer(metadata.getDisclaimer());

        return  response;
    }

    //  【模型广场】-【开始体验】-返回【langflow调用】
    @GetMapping("/getModelLangflow")
    public JsonNode getModelLangflow(@RequestParam String modelName) {
        ModelLangflow modelLangflow = modelLangflowService.getLangflowByName(modelName);
        if (modelLangflow != null) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                JsonNode langFlow = mapper.readTree(modelLangflow.getLangFlow());
                return langFlow;
            } catch (Exception e) {
                // Handle parsing exception if necessary
                e.printStackTrace();
            }
        }
        // Return an empty JSON node if no matching langflow is found or in case of an error
        return new ObjectMapper().createObjectNode();
    }

    @GetMapping("/getApplicationTemplate")
    public JsonNode getApplicationTemplate(@RequestParam String applicationName) {
        ApplicationTemplate template = applicationTemplateMapper.selectTemplateByName(applicationName);
        if (template != null) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return mapper.readTree(template.getApplicationCode());
            } catch (Exception e) {
                // Handle parsing exception if necessary
                e.printStackTrace();
            }
        }
        // Return an empty JSON node if no matching langflow is found or in case of an error
        return new ObjectMapper().createObjectNode();
    }
}
